package com.zhijian.medical.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.zhijian.medical.entity.po.*;
import com.zhijian.medical.entity.vo.request.*;
import com.zhijian.medical.entity.vo.response.*;
import com.zhijian.medical.enums.AssessmentPersonStatusEnum;
import com.zhijian.medical.enums.QuestionTypeEnum;
import com.zhijian.medical.service.*;
import com.zhijian.medical.util.AssertUtil;
import com.zhijian.medical.util.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author HCG
 * @version 1.0
 * @date 2023-02-16
 */
@Slf4j
@Service
public class MyAssessmentServiceImpl implements MyAssessmentService {

    @Autowired
    private AssessmentService assessmentService;

    @Autowired
    private AssessmentPaperService assessmentPaperService;

    @Autowired
    private AssessmentPaperQuestionService assessmentPaperQuestionService;

    @Autowired
    private AssessmentPaperPersonResultService assessmentPaperPersonResultService;

    @Autowired
    private AssessmentDscPaperPersonService assessmentDscPaperPersonService;

    @Autowired
    private AssessmentPaperPersonService assessmentPaperPersonService;

    @Autowired
    private AssessmentDetailService assessmentDetailService;

    @Autowired
    private ExamAnswerService examAnswerService;

    @Autowired
    private ExamQuestionService examQuestionService;

    @Autowired
    private PersonService personService;

    /**
     * @param assessmentSearchVo
     * @return
     */
    private List<MyAssessmentVo> selectMyList(AssessmentSearchVo assessmentSearchVo) {
        List<AssessmentVo> assessmentVos = assessmentService.selectList(assessmentSearchVo);
        if (CollectionUtil.isEmpty(assessmentVos)) {
            return Collections.emptyList();
        }
        return assessmentVos.stream().map(assessmentVo -> {
            MyAssessmentVo myAssessmentVo = new MyAssessmentVo();
            BeanUtils.copyProperties(assessmentVo, myAssessmentVo);
            //查出这个人在这次考核的状态
            List<AssessmentPaperPersonVo> assessmentPaperPersonVos = assessmentPaperPersonService.selectList(AssessmentPaperPersonSearchVo.builder()
                    .assessmentId(assessmentVo.getId())
                    .userId(assessmentSearchVo.getDoPersonId())
                    .build());
            if (CollectionUtil.isNotEmpty(assessmentPaperPersonVos)) {
                myAssessmentVo.setMyStatus(assessmentPaperPersonVos.get(0).getStatus());
                //分数
                myAssessmentVo.setMyScore(assessmentPaperPersonVos.get(0).getScore());
            } else {
                //如果没有，说明还没开始考，就是未开始状态
                myAssessmentVo.setMyStatus(AssessmentPersonStatusEnum.UN_SUBMIT.getCode().byteValue());
            }
            return myAssessmentVo;
        }).collect(Collectors.toList());

    }

    @Override
    public Page<MyAssessmentVo> selectMyPage(AssessmentSearchVo assessmentSearchVo) {
        //先直接查总数
        int count = assessmentService.count(assessmentSearchVo);
        //分页
        Page<MyAssessmentVo> page = new Page<>(true, count, assessmentSearchVo.getPageNum(), assessmentSearchVo.getPageSize());
        assessmentSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<MyAssessmentVo> responseVos = this.selectMyList(assessmentSearchVo);
        page.setData(responseVos);
        return page;
    }

    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    @Override
    public AssessmentDoingVo start(AssessmentStartVo assessmentStartVo) {

        AssessmentPaper assessmentPaper = assessmentPaperService.selectByUserIdAndAssessmentId(assessmentStartVo.getUserId(), assessmentStartVo.getAssessmentId());
        if (Objects.isNull(assessmentPaper)) {
            //如果试卷是空的，说明是第一次见，要验证+生成试卷，否则直接返回就可
            Assessment assessment = assessmentService.selectById(assessmentStartVo.getAssessmentId());
            AssertUtil.notNull(assessment, "此次考核不存在或者已被删除");
            Date now = new Date();
            Date startTime = assessment.getStartTime();
            AssertUtil.check(now.before(startTime), "还未到考核开始时间");
            Date endTime = assessment.getEndTime();
            AssertUtil.check(now.after(endTime), "此次考核已结束");
            assessmentStartVo.setWarehouseId(assessment.getExamWarehouseId());
            List<String> doPersonIds = Arrays.asList(assessment.getDoPersonIds().split(","));
            AssertUtil.check(!doPersonIds.contains(assessmentStartVo.getUserId() + ""), "你不在此次考核的名单内");
            AssessmentDetailVo assessmentDetailVo = assessmentDetailService.selectByAssessmentId(assessment.getId());
            AssertUtil.notNull(assessmentDetailVo, "此次考核没有正确生成试卷");
            BeanUtils.copyProperties(assessmentDetailVo, assessmentStartVo);
            assessmentStartVo.setDigitalSliceCaseType(assessment.getDigitalSliceCaseType());
            assessmentStartVo.setGroupIds(assessment.getGroupIds());
            assessmentStartVo.setUserType(assessment.getUserType());
            //生成这个人的试卷
            assessmentPaperService.generate(assessmentStartVo);
        } else {
            AssertUtil.check(assessmentPaper.getStatus() == AssessmentPersonStatusEnum.ALREADY_SUBMIT.getCode().byteValue() || assessmentPaper.getStatus() == AssessmentPersonStatusEnum.SCORE.getCode().byteValue(),
                    "您已经提交此次考核，请勿重复操作");
        }
        //详情，回显
        return assessmentPaperService.singleDetail(assessmentStartVo.getAssessmentId(), assessmentStartVo.getUserId());
    }

    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    @Override
    public ExamResultVo submit(AssessmentSubmitVo assessmentSubmitVo) {
        //考核id
        Long assessmentId = assessmentSubmitVo.getAssessmentId();

        //试卷
        AssessmentPaper assessmentPaper = assessmentPaperService.selectByUserIdAndAssessmentId(assessmentSubmitVo.getUserId(), assessmentId);
        AssertUtil.notNull(assessmentPaper, "此次考核不存在或者已被删除");
        Long assessmentPaperId = assessmentPaper.getId();
        //先直接删除之前的记录，重新保存
        assessmentPaperPersonResultService.deleteByAssessmentPaperIdAndUserId(assessmentPaperId, assessmentSubmitVo.getUserId());

        if (Objects.nonNull(assessmentPaper.getWarehouseId())) {
            assessmentSubmitVo.getSelectContent().forEach(contentVo -> {
                List<AssessmentPaperQuestionVo> examPaperQuestionVos = assessmentPaperQuestionService.selectList(AssessmentPaperQuestionSearchVo.builder()
                        .assessmentPaperId(assessmentPaperId)
                        .questionId(contentVo.getQuestionId())
                        .build());
                if (!CollectionUtils.isEmpty(examPaperQuestionVos)) {
                    //保存提交的选项
                    assessmentPaperPersonResultService.insert(AssessmentPaperPersonResult.builder()
                            .assessmentPaperQuestionId(examPaperQuestionVos.get(0).getId())
                            .selectAnswer(contentVo.getSelectAnswer())
                            .assessmentPaperId(assessmentPaperId)
                            .questionId(contentVo.getQuestionId())
                            .userId(assessmentSubmitVo.getUserId())
                            .assessmentId(assessmentId)
                            .build());
                }
            });
        }


        //数字切片部分的提交答案列表
        List<AssessmentSubmitVo.DscAnswerVo> dscAnswerList = assessmentSubmitVo.getDscAnswerList();
        Date now = new Date();
        if (CollectionUtil.isNotEmpty(dscAnswerList)) {
            dscAnswerList.forEach(dscAnswerVo -> {
                //查出这个做卷人在这次考核中，填写的这个病例的答案
                AssessmentDscPaperPersonVo assessmentDscPaperPersonVo = assessmentDscPaperPersonService.selectByAssessmentIdAndPersonIdAndCaseId(assessmentId, assessmentSubmitVo.getUserId(), dscAnswerVo.getId());

                if (Objects.nonNull(assessmentDscPaperPersonVo)) {
                    assessmentDscPaperPersonService.updateByPrimaryKeySelective(AssessmentDscPaperPerson.builder()
                            .id(assessmentDscPaperPersonVo.getId())
                            .answer(dscAnswerVo.getAnswer())
                            .answerRecordFilePath(dscAnswerVo.getAnswerRecordFilePath())
                            .status(AssessmentPersonStatusEnum.ALREADY_SUBMIT.getCode().byteValue())
                            .updateTime(now)
                            .build());
                }

            });
        }


        Integer score;
        if (Objects.nonNull(assessmentPaper.getWarehouseId())) {
            //直接查出做对了多少道题目
            //add by hcg @2023-12-18 这个是单选题
            Integer singleRightCount = assessmentPaperPersonResultService.selectSingleRightCountByAssessmentPaperIdAndUserId(assessmentPaperId, assessmentSubmitVo.getUserId());

            String questionIds = assessmentPaper.getQuestionIds();

            //多选题正确数目
            Integer mulRightCount = 0;
            for (String qId : questionIds.split(",")) {
                //循环试卷的题目ID
                ExamQuestion examQuestion = examQuestionService.selectById(Long.valueOf(qId));
                if (Objects.isNull(examQuestion)) {
                    continue;
                }
                if (examQuestion.getType() == QuestionTypeEnum.SINGLE_SELECTION.getCode().byteValue()) {
                    //不查单选题
                    continue;
                }
                //正确答案的对象
                List<ExamAnswerVo> examAnswerVos = examAnswerService.selectRightVoListByQuestionId(Long.valueOf(qId));
                //拼一下ID
                List<Long> rightMulIdList = examAnswerVos.stream().map(ExamAnswerVo::getId).collect(Collectors.toList());

                AssessmentPaperPersonResultVo assessmentPaperPersonResultVo = assessmentPaperPersonResultService.selectByAssessmentPaperIdAndUserIdAndQuestionId(assessmentPaperId, assessmentSubmitVo.getUserId(), Long.valueOf(qId));
                if (Objects.nonNull(assessmentPaperPersonResultVo)) {
                    String selectAnswer = assessmentPaperPersonResultVo.getSelectAnswer();
                    if (StringUtils.isNotBlank(selectAnswer)) {
                        //用户提交的这个问题的答案的ID列表
                        List<Long> selectAnswerList = Arrays.stream(selectAnswer.split(",")).map(Long::valueOf).collect(Collectors.toList());
                        if (org.apache.commons.collections4.CollectionUtils.isEqualCollection(rightMulIdList, selectAnswerList)) {
                            mulRightCount++;
                        }
                    }
                }

            }

            AssessmentDetailVo assessmentDetailVo = assessmentDetailService.selectByAssessmentId(assessmentId);

            //题库分数，取配置的，如果没有，就用2，后续这里会加入多选题的选择 todo
            score = (singleRightCount + mulRightCount) * (Objects.nonNull(assessmentDetailVo) ? assessmentDetailVo.getSingleSelectionSingleScore() : 2);
        } else {
            score = 0;
        }

        AssessmentPaperPersonVo assessmentPaperPersonVo = assessmentPaperPersonService.selectByAssessmentPaperId(assessmentPaperId);
        if (Objects.isNull(assessmentPaperPersonVo)) {
            assessmentPaperPersonService.insert(AssessmentPaperPerson.builder()
                    .assessmentPaperId(assessmentPaperId)
                    .userId(assessmentSubmitVo.getUserId())
                    .userName(assessmentSubmitVo.getUserName())
                    //如果有病例题，就改成已提交，后续要打分；如果没有病例题，只有选择题，就直接自动判分，改成已打分
                    .status(StringUtils.isNotBlank(assessmentPaper.getDigitalSliceCaseIds()) ? AssessmentPersonStatusEnum.ALREADY_SUBMIT.getCode().byteValue() :
                            AssessmentPersonStatusEnum.SCORE.getCode().byteValue())
                    //题库分数
                    .tkScore(score)
                    //如果有病例题，后续要打分，所以总分先不管；如果没有病例题，只有选择题，就直接自动判分，置为总分
                    .score(StringUtils.isNotBlank(assessmentPaper.getDigitalSliceCaseIds()) ? null : score)
                    .assessmentId(assessmentId)
                    .submitTime(now)
                    .build());
        } else {
            assessmentPaperPersonService.updateByPrimaryKeySelective(AssessmentPaperPerson.builder()
                    .id(assessmentPaperPersonVo.getId())
                    .status(StringUtils.isNotBlank(assessmentPaper.getDigitalSliceCaseIds()) ? AssessmentPersonStatusEnum.ALREADY_SUBMIT.getCode().byteValue() :
                            AssessmentPersonStatusEnum.SCORE.getCode().byteValue())
                    //题库分数
                    .tkScore(score)
                    //如果有病例题，后续要打分，所以总分先不管；如果没有病例题，只有选择题，就直接自动判分，置为总分
                    .score(StringUtils.isNotBlank(assessmentPaper.getDigitalSliceCaseIds()) ? null : score)
                    .assessmentId(assessmentId)
                    .submitTime(now)
                    .build());
        }

        //修改试卷的状态
        assessmentPaperService.updateByPrimaryKeySelective(AssessmentPaper.builder()
                .id(assessmentPaperId)
                .status(StringUtils.isNotBlank(assessmentPaper.getDigitalSliceCaseIds()) ? AssessmentPersonStatusEnum.ALREADY_SUBMIT.getCode().byteValue() :
                        AssessmentPersonStatusEnum.SCORE.getCode().byteValue())
                .build());

        return ExamResultVo.builder()
                .id(assessmentPaperId)
                .code(assessmentPaper.getCode())
                .build();
    }

    @Override
    public AssessmentDoneVo doneDetail(Long assessmentId, Long personId) {
        Person person = personService.selectById(personId);
        Assessment assessment = assessmentService.selectById(assessmentId);
        AssertUtil.notNull(assessment, "此次考核不存在或者已被删除");
        AssessmentDoingVo assessmentDoingVo = assessmentPaperService.singleDetail(assessmentId, personId);
        if (Objects.isNull(assessmentDoingVo)) {
            return null;
        }
        AssessmentDetailVo assessmentDetailVo = assessmentDetailService.selectByAssessmentId(assessmentId);
        AssertUtil.notNull(assessmentDetailVo, "此次考核不存在或者已被删除");
        AssessmentDoneVo assessmentDoneVo = new AssessmentDoneVo();
        BeanUtils.copyProperties(assessmentDoingVo, assessmentDoneVo);
        assessmentDoneVo.setSingleSelectionSingleScore(assessmentDetailVo.getSingleSelectionSingleScore());
        List<AssessmentDoingVo.ContentNewVo> content = assessmentDoingVo.getContent();
        if (CollectionUtil.isNotEmpty(content)) {
            List<AssessmentDoneVo.Content2Vo> doneContentVoList = content.stream().map(contentVo -> {
                //查出正确答案来，赋值给对象，让前端也显示下正确答案
                List<ExamAnswerVo> examAnswerVo = examAnswerService.selectRightVoListByQuestionId(contentVo.getQuestionId());
                AssessmentDoneVo.Content2Vo doneContentVo = new AssessmentDoneVo.Content2Vo();
                BeanUtils.copyProperties(contentVo, doneContentVo);

                if (CollectionUtil.isNotEmpty(examAnswerVo)) {
                    //正确答案的ID数组
                    List<Long> answerIdList = examAnswerVo.stream().map(ExamAnswerVo::getId).collect(Collectors.toList());
                    //这个人选择的
                    String selectAnswer = doneContentVo.getSelectAnswer();
                    if (StringUtils.isNotBlank(selectAnswer)) {
                        List<Long> selectAnswerIdList = Arrays.stream(selectAnswer.split(",")).map(Long::valueOf).collect(Collectors.toList());
                        //如果相等，就是做对了，否则就是错误
                        doneContentVo.setRight(org.apache.commons.collections4.CollectionUtils.isEqualCollection(selectAnswerIdList, answerIdList) ? 1 : 0);
                    } else {
                        //错误
                        doneContentVo.setRight(0);
                    }
                    doneContentVo.setRightAnswer(com.zhijian.medical.util.StrUtil.join(",", answerIdList));
                } else {
                    //错误
                    doneContentVo.setRight(0);
                }
                return doneContentVo;
            }).collect(Collectors.toList());
            assessmentDoneVo.setContent(doneContentVoList);
        }
        List<DigitalSliceCaseVo> digitalSliceCaseList = assessmentDoingVo.getDigitalSliceCaseList();
        if (CollectionUtil.isNotEmpty(digitalSliceCaseList)) {
            List<AssessmentReviewerOfDigitalSliceCaseVo> collect = digitalSliceCaseList.stream().map(digitalSliceCaseVo -> {
                AssessmentReviewerOfDigitalSliceCaseVo assessmentReviewerOfDigitalSliceCaseVo = new AssessmentReviewerOfDigitalSliceCaseVo();
                BeanUtils.copyProperties(digitalSliceCaseVo, assessmentReviewerOfDigitalSliceCaseVo);
                //查出这个做卷人在这次考核中，填写的这个病例的答案，与阅卷人在这次考核中，给这个人填的评语与评分，组装出来
                AssessmentDscPaperPersonVo assessmentDscPaperPersonVo = assessmentDscPaperPersonService.selectByAssessmentIdAndPersonIdAndCaseId(assessmentId, personId, digitalSliceCaseVo.getId());
                if (Objects.nonNull(assessmentDscPaperPersonVo)) {
                    assessmentReviewerOfDigitalSliceCaseVo.setAnswer(assessmentDscPaperPersonVo.getAnswer());
                    assessmentReviewerOfDigitalSliceCaseVo.setAnswerRecordFilePath(assessmentDscPaperPersonVo.getAnswerRecordFilePath());
                    assessmentReviewerOfDigitalSliceCaseVo.setComment(assessmentDscPaperPersonVo.getComment());
                    assessmentReviewerOfDigitalSliceCaseVo.setCommentRecordFilePath(assessmentDscPaperPersonVo.getCommentRecordFilePath());
                    assessmentReviewerOfDigitalSliceCaseVo.setScore(assessmentDscPaperPersonVo.getScore());
                }
                return assessmentReviewerOfDigitalSliceCaseVo;
            }).collect(Collectors.toList());
            assessmentDoneVo.setDigitalSliceCaseList(collect);
        }
        //姓名
        assessmentDoneVo.setPersonName(Objects.nonNull(person) ? person.getName() : "");
        //这个人的考核表
        AssessmentPaperPersonVo assessmentPaperPersonVo = assessmentPaperPersonService.selectByAssessmentIdAndPersonId(assessmentId, personId);
        if (Objects.nonNull(assessmentPaperPersonVo) && assessmentPaperPersonVo.getStatus() == 3) {
            assessmentDoneVo.setScore(assessmentPaperPersonVo.getScore());
        }
        return assessmentDoneVo;
    }

    @Override
    public boolean fix(Long assessmentId) {
        Assessment assessment = assessmentService.selectById(assessmentId);
        AssertUtil.notNull(assessment, "此次考核不存在或者已被删除");
        String doPersonIds = assessment.getDoPersonIds();
//        String doPersonIds = "147";
        for (String personIdStr : doPersonIds.split(",")) {
            Long personId = Long.valueOf(personIdStr);
            AssessmentDoingVo assessmentDoingVo = assessmentPaperService.singleDetail(assessmentId, personId);
            if (Objects.isNull(assessmentDoingVo)) {
                continue;
            }
            //状态
            Byte status = assessmentDoingVo.getStatus();
            if (status == 0) {
                //如果未提交，就忽略
                continue;
            }
            AssessmentDetailVo assessmentDetailVo = assessmentDetailService.selectByAssessmentId(assessmentId);
            AssertUtil.notNull(assessmentDetailVo, "此次考核不存在或者已被删除");
            AssessmentDoneVo assessmentDoneVo = new AssessmentDoneVo();
            BeanUtils.copyProperties(assessmentDoingVo, assessmentDoneVo);
            List<AssessmentDoingVo.ContentNewVo> content = assessmentDoingVo.getContent();
            if (CollectionUtil.isNotEmpty(content)) {
                //对的题目
                final Integer[] right = {0};
                List<AssessmentDoneVo.Content2Vo> doneContentVoList = content.stream().map(contentVo -> {
                    //查出正确答案来，赋值给对象，让前端也显示下正确答案
                    List<ExamAnswerVo> examAnswerVo = examAnswerService.selectRightVoListByQuestionId(contentVo.getQuestionId());
                    AssessmentDoneVo.Content2Vo doneContentVo = new AssessmentDoneVo.Content2Vo();
                    BeanUtils.copyProperties(contentVo, doneContentVo);

                    if (CollectionUtil.isNotEmpty(examAnswerVo)) {
                        //正确答案的ID数组
                        List<Long> answerIdList = examAnswerVo.stream().map(ExamAnswerVo::getId).collect(Collectors.toList());
                        //这个人选择的
                        String selectAnswer = doneContentVo.getSelectAnswer();
                        if (StringUtils.isNotBlank(selectAnswer)) {
                            List<Long> selectAnswerIdList = Arrays.stream(selectAnswer.split(",")).map(Long::valueOf).collect(Collectors.toList());
                            //如果相等，就是做对了，否则就是错误
                            if (org.apache.commons.collections4.CollectionUtils.isEqualCollection(selectAnswerIdList, answerIdList)) {
                                doneContentVo.setRight(1);
                                right[0]++;
                            } else {
                                doneContentVo.setRight(0);
                            }
                        } else {
                            //错误
                            doneContentVo.setRight(0);
                        }
                        doneContentVo.setRightAnswer(com.zhijian.medical.util.StrUtil.join(",", answerIdList));
                    } else {
                        //错误
                        doneContentVo.setRight(0);
                    }
                    return doneContentVo;
                }).collect(Collectors.toList());
                AssessmentPaperPerson assessmentPaperPerson = new AssessmentPaperPerson();
                assessmentPaperPerson.setTkScore(right[0] * 2);
                assessmentPaperPerson.setUserId(personId);
                assessmentPaperPerson.setAssessmentId(assessmentId);
                assessmentPaperPersonService.updateByUserIdAndAssessmentId(assessmentPaperPerson);

                System.out.println(personId + " 对的题目是 " + right[0] + " 道");
            }

        }
        return true;

    }

}
